<template>
    <div>
        <video ref="selfVideo" autoplay class="video"></video>
        <video ref="remoteVideo" autoplay class="video"></video>

        <div>
            <a-button type="link">打开麦克风</a-button>
            <a-button type="link">关闭麦克风</a-button>
            <a-button @click="openVideo" type="link">打开摄像头</a-button>
            <a-button @click="closeVideo" type="link">关闭摄像头</a-button>
        </div>
    </div>
</template>
<script setup lang="ts">
import { onMounted, onUnmounted, ref } from 'vue';
import { eventBus, MessageType, sendMessage, type Message } from './socket';
import { useMeetingStore } from '@/stores/meeting';


const meetingStore = useMeetingStore()
const selfVideo = ref();
const remoteVideo = ref();
const pcMap: Map<string, RTCPeerConnection> = new Map()
let localStream: MediaStream
const candidateList: RTCIceCandidate[] = []

const createOffer = async (member: any) => {
    const pc = new RTCPeerConnection();
    pcMap.set(member.id, pc)

    pc.ontrack = ({ track, streams }) => {
        track.onunmute = () => {

            // if (remoteVideo.value.srcObject) {
            //     return;
            // }
            remoteVideo.value.srcObject = streams[0];
        };

    };
    let makingOffer = false;

    pc.onnegotiationneeded = async () => {
        try {
            makingOffer = true;
            await pc.setLocalDescription();
            console.log(pc.localDescription)
            // signaler.send({ description: pc.localDescription });
            sendMessage({
                messageType: MessageType.PERSON,
                senderId: meetingStore.id,
                senderName: meetingStore.name,
                targetId: member.id,
                content: pc.localDescription
            })
        } catch (err) {
            console.error(err);
        } finally {
            makingOffer = false;
        }
    };
    pc.onicecandidate = ({ candidate }) => {
        console.log(candidate)

        sendMessage({
            messageType: MessageType.PERSON,
            senderId: meetingStore.id,
            senderName: meetingStore.name,
            targetId: member.id,
            content: candidate
        })
    }
    await craeteMySteam(pc)

    return pc
}

const createAnswer = async (message: Message) => {
    const description = message.content
    if (!description) {
        return
    }
    if (description.type === "offer") {
        const pc = new RTCPeerConnection();
        pcMap.set(message.senderId, pc)

        pc.ontrack = ({ track, streams }) => {

            track.onunmute = () => {
                // if (remoteVideo.value.srcObject) {
                //     return;
                // }
                remoteVideo.value.srcObject = streams[0];
            };

        };
        pc.onicecandidate = ({ candidate }) => {
            console.log(candidate)

            sendMessage({
                messageType: MessageType.PERSON,
                senderId: meetingStore.id,
                senderName: meetingStore.name,
                targetId: message.senderId,
                content: candidate
            })
        }
        await craeteMySteam(pc)
        await pc.setRemoteDescription(description);
        await pc.setLocalDescription();

        sendMessage({
            messageType: MessageType.PERSON,
            senderId: meetingStore.id,
            senderName: meetingStore.name,
            targetId: message.senderId,
            content: pc.localDescription
        })
        for (let c of candidateList) {
            await pcMap.get(message.senderId)!.addIceCandidate(c)
        }
    } else if (description.type === "answer") {

        await pcMap.get(message.senderId)!.setRemoteDescription(description);
        for (let c of candidateList) {
            await pcMap.get(message.senderId)!.addIceCandidate(c)
        }
    } else {
        console.log('addIceCandidate start...')
        // await pcMap.get(message.senderId)!.addIceCandidate(description)
        candidateList.push(description)
    }





}

const craeteMySteam = async (pc: RTCPeerConnection) => {

    try {
        if (!localStream) {
            localStream = await navigator.mediaDevices.getUserMedia({ audio: true, video: true });
        }


        for (const track of localStream.getTracks()) {

            pc.addTrack(track, localStream);
        }

        selfVideo.value.srcObject = localStream;
        // selfVideo.value.play()
    } catch (err) {
        console.error(err);
    }
}

const onmessage = async (event: any) => {
    const message: Message = JSON.parse(event.data);

    console.log("video list onmessage:")
    console.log(message)
    if (message.messageType == MessageType.PERSON) {
        createAnswer(message)
    }
}

const openVideo = async () => {
    let stream = await navigator.mediaDevices.getUserMedia({ video: true });
    let tracks: MediaStreamTrack[] = stream.getVideoTracks()

    for (let track of tracks) {
        localStream.addTrack(track)
        // for(const [id, pc] of pcMap){
        //     pc.addTrack(track, localStream);
        // }

    }
}

const closeVideo = () => {
    let tracks: MediaStreamTrack[] = localStream.getVideoTracks()

    for (let track of tracks) {
        track.stop()
        localStream.removeTrack(track)
    }

}

onMounted(() => {
    eventBus.on('call', createOffer)
    eventBus.on("onmessage", onmessage)
})
onUnmounted(() => {
    for (const [id, pc] of pcMap) {
        pc.close()
    }
})
</script>
<style scoped>
.video {
    background: #000;
    display: inline-block;
    margin: 20px;
    width: 200px;
    height: 200px;
}
</style>